# BSD3.0
# cili@163.com

import os
import json
import logging
import sys
from webserver import WebServer
from wsserver import WebSocketServer
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox, simpledialog
from datetime import datetime
import threading

class MDServer:
    def __init__(self):
        # 初始化颜色和字体字典
        self.colors = {
            'bg': '#FFFFFF',           # 主背景色
            'status_bg': '#FAFAFA',    # 状态栏背景色
            'selected': '#E6F4FF',     # 选中项背景色
            'hover': '#F5F5F5',        # 悬停项背景色
            'selected_fg': '#1677FF'   # 选中项文字颜色
        }
        
        self.fonts = {
            'title': (None, 16, 'bold'),     
            'button': (None, 10),            
            'listbox': (None, 11),    
            'list_title': (None, 12, 'bold'),  
            'status': (None, 9)              
        }
        
        # 初始化基本配置
        self.projects = {}
        self.project_versions = {}
        self.load_projects()
        self.ensure_project_directory()
        self.ws_server = WebSocketServer(self)
        self.web_server = WebServer()
        self.run_flag = False
        self.server_thread = None

        # 创建并配置GUI
        self.create_gui()
        self.style_config()

    def style_config(self):
        style = ttk.Style()
        
        # 配置主题样式
        style.configure('TLabel', 
                       font=self.fonts['button'])
        
        style.configure('Title.TLabel',
                       font=self.fonts['title'])
        
        style.configure('TButton', 
                       font=self.fonts['button'])
        
        style.configure('Treeview', 
                       font=self.fonts['listbox'],
                       rowheight=25)
        
        style.configure('Treeview.Heading', 
                       font=self.fonts['list_title'])
        
        # 配置悬停和选中效果
        style.map('Treeview',
                 background=[('selected', self.colors['selected']),
                           ('hover', self.colors['hover'])],
                 foreground=[('selected', self.colors['selected_fg'])])

    def create_gui(self):
        self.root = tk.Tk()
        self.root.title("MD 协作文档服务器")
        self.root.geometry("800x700")
        self.root.configure(bg=self.colors['bg'])
        
        # 添加��口关闭处理
        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)

        # 添加窗口图标（如果有的话）
        try:
            self.root.iconbitmap('icon.ico')
        except:
            pass

        self.create_widgets()

    def create_widgets(self):
        # 主框架
        main_frame = ttk.Frame(self.root, padding="30 20")
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 标题
        title_label = ttk.Label(main_frame,
                              text="MD 协作文档管理系统",
                              style='Title.TLabel')
        title_label.pack(pady=(0, 30))

        # 内容区域
        content_frame = ttk.Frame(main_frame)
        content_frame.pack(fill=tk.BOTH, expand=True)

        # 按钮区域
        button_frame = ttk.Frame(content_frame, padding="20")
        button_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 10))

        # 创建按钮
        self.toggle_button = ttk.Button(button_frame,
                                      text="启动服务",
                                      command=self.toggle_server)
        self.toggle_button.pack(pady=(0, 10), fill=tk.X)

        buttons = [
            ("创建项目", self.create_project),
            ("显示密码", self.show_password),
            ("修改密码", self.change_password),
            ("删除项目", self.delete_project)
        ]

        for text, command in buttons:
            btn = ttk.Button(button_frame, text=text, command=command)
            btn.pack(pady=5, fill=tk.X)

        # 项目列表区域
        list_frame = ttk.Frame(content_frame, padding="20")
        list_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)

        list_label = ttk.Label(list_frame,
                             text="项目列表",
                             style='Title.TLabel')
        list_label.pack(pady=(0, 10), anchor='w')

        # 创建带滚动条的列表容器
        list_container = ttk.Frame(list_frame)
        list_container.pack(fill=tk.BOTH, expand=True)

        # 创建 Treeview
        self.project_listbox = ttk.Treeview(list_container,
                                          show="tree",
                                          selectmode="browse")
        self.project_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        # 创建滚动条
        scrollbar = ttk.Scrollbar(list_container,
                                orient="vertical",
                                command=self.project_listbox.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 配置 Treeview 的滚动
        self.project_listbox.configure(yscrollcommand=scrollbar.set)

        # 配置悬停标签
        self.project_listbox.tag_configure('hover',
                                         background=self.colors['hover'])

        # 绑定鼠标事件
        self.project_listbox.bind('<Motion>', self.on_listbox_motion)
        self.project_listbox.bind('<Leave>', self.on_listbox_leave)

        # 状态显示区域
        status_frame = ttk.Frame(main_frame, padding="10")
        status_frame.pack(fill=tk.BOTH, expand=True)

        self.status_text = tk.Text(status_frame,
                                 height=6,
                                 font=self.fonts['status'],
                                 bg=self.colors['status_bg'],
                                 relief=tk.FLAT,
                                 padx=10,
                                 pady=10)
        self.status_text.pack(fill=tk.BOTH, expand=True)

        self.update_project_list()

    def ensure_project_directory(self):
        if not os.path.exists('mdproject'):
            os.makedirs('mdproject')

    def load_projects(self):
        if os.path.exists('mdproject/projects.json'):
            with open('mdproject/projects.json', 'r') as f:
                self.projects = json.load(f)

    def save_projects(self):
        with open('mdproject/projects.json', 'w') as f:
            json.dump(self.projects, f)

    def toggle_server(self):
        if not self.run_flag:
            self.start()
            self.toggle_button.configure(text="停止服务")
            self.log_status("服务已启动，通过 http://[ip]:8080 进行访问。")
        else:
            self.stop()
            self.toggle_button.configure(text="启动服务")
            self.log_status("服务已停止")

    def create_project(self):
        project_name = simpledialog.askstring("新建项目", "请输入项目名称:",parent=self.root)
        if project_name:
            if project_name in self.projects:
                messagebox.showerror("错误", "项目已存在")
                return

            password = simpledialog.askstring("设置密码", "请输入项目密码:",parent=self.root)
            if password:
                self.projects[project_name] = password
                self.save_projects()
                os.makedirs(f"mdproject/{project_name}", exist_ok=True)
                self.save_project_content(project_name, "# 新项目\n\n开始编辑吧！")
                self.update_project_list()
                self.log_status(f"项目 '{project_name}' 创建成功")

    def show_password(self):
        selected = self.project_listbox.selection()
        if selected:
            project_name = self.project_listbox.item(selected[0])['text']
            password = self.projects[project_name]
            messagebox.showinfo("项目密码", f"项目 '{project_name}' 的密码是: {password}")
        else:
            messagebox.showerror("错误", "未选择项目")

    def change_password(self):
        selected = self.project_listbox.selection()
        if selected:
            project_name = self.project_listbox.item(selected[0])['text']
            old_password = simpledialog.askstring("旧密码", "请输入旧密码:",parent=self.root)
            if old_password == self.projects[project_name]:
                new_password = simpledialog.askstring("新密码", "请输入新密码:",parent=self.root)
                if new_password:
                    self.projects[project_name] = new_password
                    self.save_projects()
                    messagebox.showinfo("信息", f"项目 '{project_name}' 密码修改成功")
                    self.log_status(f"项目 '{project_name}' 密码修改成功")
            else:
                messagebox.showerror("错误", "旧密码不正确")
        else:
            messagebox.showerror("错误", "未选择项目")

    def delete_project(self):
        selected = self.project_listbox.selection()
        if selected:
            project_name = self.project_listbox.item(selected[0])['text']
            password = simpledialog.askstring("确认密码", "请输入项目密码:",parent=self.root)
            if password == self.projects[project_name]:
                del self.projects[project_name]
                project_path = f"mdproject/{project_name}"
                if os.path.exists(project_path):
                    import shutil
                    shutil.rmtree(project_path)
                self.save_projects()
                self.update_project_list()
                messagebox.showinfo("信息", f"项目 '{project_name}' 删除成功")
                self.log_status(f"项目 '{project_name}' 删除成功")
            else:
                messagebox.showerror("错误", "密码不正确")
        else:
            messagebox.showerror("错误", "未选择项目")

    def verify_project(self, project, password):
        return self.projects.get(project) == password

    def get_project_content(self, project):
        doc_path = f"mdproject/{project}/doc.md"
        if os.path.exists(doc_path):
            with open(doc_path, 'r', encoding='utf-8') as f:
                return f.read()
        return ''

    def save_project_content(self, project, content):
        os.makedirs(f"mdproject/{project}", exist_ok=True)
        doc_path = f"mdproject/{project}/doc.md"
        with open(doc_path, 'w', encoding='utf-8') as f:
            f.write(content)

    def start(self):
        self.run_flag = True
        self.server_thread = threading.Thread(target=self.start_servers)
        self.server_thread.daemon = True
        self.server_thread.start()

    def start_servers(self):
        self.web_server.start()
        self.ws_server.start()

    def stop(self):
        if self.run_flag:
            self.run_flag = False
            self.ws_server.stop()
            self.web_server.stop()
            if self.server_thread and self.server_thread.is_alive():
                self.server_thread.join(timeout=2)

    def handle_update(self, project, content, version):
        current_version = self.project_versions.get(project, 0)
        if version > current_version:
            self.project_versions[project] = version
            self.save_project_content(project, content)
            return True
        return False

    def update_project_list(self):
        for item in self.project_listbox.get_children():
            self.project_listbox.delete(item)

        for name in self.projects.keys():
            self.project_listbox.insert('', 'end', text=name)

    def log_status(self, message):
        self.status_text.insert('1.0', f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")} {message}\n')
        self.status_text.see('1.0')

    def on_listbox_motion(self, event):
        item = self.project_listbox.identify_row(event.y)
        if item:
            for i in self.project_listbox.get_children():
                self.project_listbox.item(i, tags=())
            self.project_listbox.item(item, tags=('hover',))

    def on_listbox_leave(self, event):
        for item in self.project_listbox.get_children():
            self.project_listbox.item(item, tags=())

    def on_closing(self):
        self.stop()
        self.root.quit()
        self.root.destroy()
        import _thread
        _thread.interrupt_main()
        sys.exit(0)

    def run(self):
        self.root.mainloop()


if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    server = MDServer()
    try:
        server.run()
    except KeyboardInterrupt:
        server.stop()
